/*
 * FindAnswer2.cpp
 * Created on: 03/03/2011
 * Author: catharine
 */

#include "FindAnswer2.h"

void verticalValues(int* verticalSizes, int* verticalInitial, IplImage* image,
		int vSize) {
	int height = image->height;
	int counter = 0;
	for (int x = 5; x < 6; x++) {
		for (int y = 5; y < height; y++) {
			int size = 0;
			if (cvGetReal2D(image, y, x) == 0) {
				if (counter < vSize) {
					verticalInitial[counter] = y;
				}

				while (true) {
					if (y < height - 1 && cvGetReal2D(image, y, x) == 0) {
						y++;
						size++;
					} else {
						break;
					}
				}

				if (counter < vSize) {
					verticalSizes[counter] = size;
				}
				counter++;
			}
		}
	}
}

void horizontalValues(int * horizontalSizes, int * horizontalInitial,
		IplImage * img, int hSize) {
	int width = img->width;
	int counter = 0;
	for (int y = 5; y < 6; y++) {
		for (int x = 5; x < width; x++) {
			int size = 0;
			if (cvGetReal2D(img, y, x) == 0) {
				if (counter < hSize) {
					horizontalInitial[counter] = x;
				}

				while (true) {
					if (x < width - 1 && cvGetReal2D(img, y, x) == 0) {
						x++;
						size++;
					} else {
						break;
					}
				}

				if (counter < hSize) {
					horizontalSizes[counter] = size;
				}
				counter++;
			}
		}
	}
}

double findNumberBlackPixels(IplImage* image, int height, int width) {
	double sum = 0;
	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			if (cvGetReal2D(image, i, j) == 0) {
				sum++;
			}
		}
	}
	return sum;
}

void findSumROI(double **sumROI, IplImage* image, int vSize, int hSize,
		int* horizontalInitial, int* horizontalSizes, int* verticalInitial,
		int* verticalSizes, int middle) {
	for (int i = 0; i < hSize; i++) {
		for (int j = 0; j < vSize; j++) {
			int width = horizontalSizes[i];
			int height = verticalSizes[j];
			cvSetImageROI(image, cvRect(horizontalInitial[i],
					verticalInitial[j], width, height));
			if (j < middle) {
				sumROI[i][j] = findNumberBlackPixels(image, height, width);
			} else {
				sumROI[i + 16][j - 5] = findNumberBlackPixels(image, height,
						width);
			}
			cvResetImageROI(image);
		}
	}
}

void createArchieve(String name, string* array, int arraySize) {
	ofstream arquivo;
	arquivo.open(name.c_str());

	for (int i = 0; i < arraySize; i++) {
		arquivo << array[i] << endl;
	}
	arquivo.close();
}

void createArchieve(string name, string content) {
	ofstream arquivo;
	arquivo.open(name.c_str());
	arquivo << content;
	arquivo.close();
}

string findAnswer(double** sumROI, int doublee, int middle, double threshold1) {
	stringstream s;
	s << "";
	for (int i = 0; i < doublee; i++) {
		int lengthBefore = s.str().length();
		for (int j = 0; j < middle; j++) {
			if (sumROI[i][j] >= threshold1) {
				if (j == 0) {
					s << "A";
				} else if (j == 1) {
					s << "B";
				} else if (j == 2) {
					s << "C";
				} else if (j == 3) {
					s << "D";
				} else {
					s << "E";
				}
			}
		}
		int lengthAfter = s.str().length();
		if (lengthAfter == lengthBefore) {
			s << "V";
		}
	}
	return s.str();
}

string fileName(int i) {
	stringstream name;
	name << "GabaritosRotacionados/Gabarito" << i;
	return name.str();
}

string compareAnswers(const char * archieveFileName, const char * answerFileName) {
	ifstream archieve(archieveFileName);
	ifstream answer(answerFileName);

	string lineAnswer;
	string lineArchieve;
	string nameImageArchieve;
	string nameImageAnswer;

	stringstream a;
	a << "";
	while (true) {
		archieve >> nameImageArchieve >> lineArchieve;
		answer >> nameImageAnswer >> lineAnswer;

		if (archieve.eof() && answer.eof()) {
			break;
		}

		if (lineAnswer.compare(lineArchieve) != 0) {
			int size = lineAnswer.size();
			a << "Imagem: ";
			a << nameImageAnswer;
			a << "\n";
			a << "Questões com erro. \n";

			for (int i = 0; i < size; i++) {
				if (lineAnswer[i] != lineArchieve[i]) {
					a << "Encontrado: ";
					a << (i + 1);
					a << lineAnswer[i];
					a << ".  ";

					a << "Esperado: ";
					a << (i + 1);
					a << lineArchieve[i];
					a << ".\n";
				}
			}
			a << "\n";
		}
	}
	archieve.close();
	answer.close();
	return a.str();
}

int main(int argc, char **argv) {
	if (argc < 3) {
		cout << "Para que o programa esse executado corretamente insira"
				<< " os 3 dados necessarios." << endl;
		cout << "1º: Programa." << endl << "2º: Limiar." << endl;
		cout << "3º: O arquivo com o gabarito das marcações." << endl;

	} else {
		double threshold1 = atof(argv[1]);

		int numberDocuments = 5;
		string content;
		for (int i = 1; i <= numberDocuments; i++) {
			string picture = fileName(i);

			IplImage* image = cvLoadImage(
					picture.append("Rotacionado.bmp").c_str());

			IplImage * imageGS = cvCreateImage(cvGetSize(image), 8, 1);
			IplImage * dst = cvCreateImage(cvGetSize(image), 8, 1);

			double percent = (770 / double(dst->width)) * 100;

			IplImage * dst2 = cvCreateImage(cvSize(
					(int) ((dst->width * percent) / 100), (int) ((dst->height
							* percent) / 100)), 8, 1);

			cvCvtColor(image, imageGS, CV_RGB2GRAY);

			const int hSize = 16;
			const int vSize = 10;
			const int doublee = hSize * 2;
			const int middle = vSize / 2;

			int* horizontalSizes = new int[hSize];
			int* horizontalInitial = new int[hSize];

			int* verticalSizes = new int[vSize];
			int* verticalInitial = new int[vSize];

			cvAdaptiveThreshold(imageGS, dst, 255, CV_ADAPTIVE_THRESH_MEAN_C,
					CV_THRESH_BINARY, 151, 5);

			cvResize(dst, dst2);

			horizontalValues(horizontalSizes, horizontalInitial, dst2, hSize);
			verticalValues(verticalSizes, verticalInitial, dst2, vSize);

			double ** sumROI = new double*[doublee];
			for (int i = 0; i < doublee; i++) {
				sumROI[i] = new double[middle];
			}

			findSumROI(sumROI, dst2, vSize, hSize, horizontalInitial,
					horizontalSizes, verticalInitial, verticalSizes, middle);

			content.append(picture);
			content.append(" ");
			content.append(findAnswer(sumROI, doublee, middle, threshold1));
			content.append("\n");

			cvReleaseImage(&image);
			cvReleaseImage(&imageGS);
			cvReleaseImage(&dst);
			cvReleaseImage(&dst2);
		}

		string file = "Respostas.txt";
		createArchieve(file, content);

		string comparison;
		comparison.append(compareAnswers(argv[2], file.c_str()));

		string newFile = "ComparacaoDasRespostas.txt";
		createArchieve(newFile, comparison);
	}
}
